﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WpsReplace
{
    public partial class Form1 : Form
    {
        Regex regex = new Regex(@"(\d{4}-\d{1,2}-\d{1,2})");
        Regex regex2 = new Regex(@"(\d{4}/\d{1,2}/\d{1,2})");
        Regex regex3 = new Regex(@"(\d{4}\.\d{1,2}\.\d{1,2})");
        Regex regex4 = new Regex(@"(\d{4}年\d{1,2}月\d{1,2})");        
        Regex regex4_2 = new Regex(@"(\d{4}年\d{1,2}月)\D{0,}");
        Regex regex5 = new Regex(@"(\d{4}年)\D{0,}");
        Regex regex6 = new Regex(@"\D{0,}(\d{8})\D{0,}");
        Dictionary<string,Regex> regexMap = new Dictionary<string,Regex>();
        List<string> others = new List<string>();
        List<string> extends = new List<string>();


      
  
       
       
      
        public Form1()
        {
            InitializeComponent();

            init();

        }

        private void init() {
            regexMap.Add("yyyy-MM-dd", regex);
            regexMap.Add("yyyy/MM/dd", regex2);
            regexMap.Add("yyyy.MM.dd", regex3);
            regexMap.Add("yyyy年MM月dd", regex4);
            regexMap.Add("yyyy年MM月", regex4_2);
            regexMap.Add("yyyy年", regex5);
            extends.Add(".doc");
            extends.Add(".docx");
            extends.Add(".xlsx");
            extends.Add(".xls");
            if (File.Exists("other.txt"))
            {
                string other = File.ReadAllText("other.txt");
                textBox3.Text = other;
                string[] line = other.Split("\r\n".ToArray());
                foreach (string l in line)
                {
                    if (string.IsNullOrEmpty(l) == false)
                    {
                        others.Add(l);
                    }
                }
                setLableText();
            }
            else
            {
                File.Create("other.txt");
            }

            if (File.Exists("time.txt"))
            {
                string[] lines = File.ReadAllLines("time.txt");
            }
            
        }

        private void MonitorWindows() {
            WinApi.CALLBACK callBack = new WinApi.CALLBACK(chooseWindows);

            foreach(Process p in Process.GetProcesses()) {
                if (p.ProcessName == "wps" || p.ProcessName == "et") {
                    WinApi.EnumWindows(callBack, p.Id);
                }                
            }
            
        }

        private  bool chooseWindows(int hwnd, int lparm)
        {
            StringBuilder title = new StringBuilder(100);
            WinApi.GetWindowText(hwnd, title, 100);
            Console.WriteLine(title.ToString());

            return true;
        }

        private void setLableText() {
            if (this.InvokeRequired)
            {
                MethodInvoker m = new MethodInvoker(() =>
                {
                    label1.Text = textBox3.Lines.Length + "条规则  剩余" + listBox1.Items.Count + "个文件";
                });
                this.Invoke(m);
            }
            else {
                label1.Text = textBox3.Lines.Length + "条规则  剩余" + listBox1.Items.Count + "个文件";
            }
        }

        private void excelReplace(string filePath) {
            Excel.Application exapplication = null;
            exapplication = new Excel.Application();
            exapplication.DisplayAlerts = false;
            exapplication.Visible = false;
            Excel.Workbook workbook = exapplication.Workbooks.Open(filePath);
            Excel.Sheets sheets = workbook.Worksheets;            
            if (sheets.Count > 0)
            {
                var enumerator = sheets.GetEnumerator();
                while (enumerator.MoveNext()) {
                    Excel.Worksheet sheet = enumerator.Current as Excel.Worksheet;

                    if (checkBox1.Checked) {
                        string sheetName = replaceSheetName(sheet.Name);
                        sheet.Name = sheetName;
                    }

                    Excel.Range range = sheet.UsedRange; 

                    StringBuilder stringBuilder = new StringBuilder();
                    var cellEnumerator = range.GetEnumerator();
                    while (cellEnumerator.MoveNext())
                    {
                        Excel.Range r = cellEnumerator.Current as Excel.Range;                      
                        string text = r.Text;              
                        object value = r.Value;
                        if (value != null) {
                            if (value is string)
                            {
                                stringBuilder.Append(text + " ");
                            }
                            else if (value is DateTime) {
                                //int month = (int)numericUpDown1.Value;
                                //r.Value.AddMonths(month);
                                r.NumberFormat = "@";
                                r.Value = text;
                                stringBuilder.Append(text + " ");                                
                                
                            }
                        }
                       
                        stringBuilder.Append(text + " ");
                    }
                    //Console.WriteLine(stringBuilder.ToString());
                    relaceExcel(stringBuilder.ToString(), range);
                }
                             
            }
            try
            {
                workbook.Save();
                workbook.Close();
            }
            catch { 
            }
            
            exapplication.Quit();
            killProcess(exapplication.Hwnd);
        }

        private string replaceSheetName(string sheetName) {       
            foreach (string key in regexMap.Keys)
            {
                Regex rg = regexMap[key];
                MatchCollection matchCollection = rg.Matches(sheetName);
                if (matchCollection.Count > 0)
                {
                    foreach (Match match in matchCollection)
                    {
                        string find = match.Groups[1].Value;
                        string replace = dealDateTime(find, key);                        
                        sheetName= sheetName.Replace(find, replace);
                    }
                }
            }
            MatchCollection ms = regex6.Matches(sheetName);
            if (ms.Count > 0) {
                foreach (Match match in ms)
                {
                    string find = match.Groups[1].Value;
                    string replace = dealDateTime(find, "yyyyMMdd");
                    sheetName = sheetName.Replace(find, replace);
                }
            }

            return sheetName;

        }

        private void killProcess(int handle) {
            try
            {
                int pid = 0;
                WinApi.GetWindowThreadProcessId(new IntPtr(handle), out pid);

                if (pid > 0)
                {
                    Process p = Process.GetProcessById(pid);
                    p.Kill();
                    p.WaitForExit();

                }
            }
            catch (Exception ex) { }
        }
        private void wordReplace(string filePath) {
            

            Word.Application wdapplication = null;
            wdapplication = new Word.Application();
            wdapplication.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone;
            wdapplication.Visible = false;
            Object missing = System.Reflection.Missing.Value;
            Word.Document document = wdapplication.Documents.Open(filePath);
            if (checkBox2.Checked) {
                foreach (Word.Section section in document.Sections)
                {
                    foreach (Word.HeaderFooter header in section.Headers)
                    {
                        header.Range.Delete();
                    }
                    foreach (Word.HeaderFooter footer in section.Footers) {
                        footer.Range.Delete();
                    }
                }
            }
            
            Word.Range range = document.Content;
            repalceWord(range);
            foreach (Word.Shape shape in document.Shapes)
            {
                try
                {
                    repalceWord(shape.TextFrame.TextRange);
                }
                catch (Exception ex) { 
                    
                }
            }
            try
            {
                document.Close(Word.WdSaveOptions.wdSaveChanges);
                wdapplication.Quit(missing, missing, missing);
            }
            catch (Exception ex)
            {
            }
        }

        private void relaceExcel(string content, Excel.Range range) {
            List<string> replaceList = getRepalce(content);
            replaceList.AddRange(others);
            foreach (string replace in replaceList)
            {
                //Console.WriteLine(replace );
                if (string.IsNullOrEmpty(replace)||replace.Contains("|") ==false) continue;
                int index = replace.LastIndexOf("|");
                string find = replace.Substring(0, index);
                string rp = replace.Substring(++index);
                if (find == rp) continue;
                Excel.Range finded = range.Find(find);
                if (finded == null) continue;
                finded.Replace(find, rp);

                Excel.Range next = range.FindNext();
                while (next != null) {
                    next.Replace(find, rp);
                    next = range.FindNext();
                }
            }

        }

        private void repalceWord(Word.Range range) {
        
            List<string> replaceList = getRepalce(range.Text);
            replaceList.AddRange(others);
            Object nothing = System.Reflection.Missing.Value;
            foreach (string replace in replaceList)
            {
                if(string.IsNullOrEmpty(replace)||replace.Contains("|") ==false) continue ;
                int index = replace.LastIndexOf("|");
                string find = replace.Substring(0,index );
                string rp = replace.Substring(++index);
                Word.Find fd = range.Find;
                fd.Execute(find, nothing, nothing, nothing, nothing, nothing, nothing, nothing, nothing, rp, 2);
            }
        }


        private List<string> getRepalce(string content) {
            List<string> list = new List<string>();
            if (checkBox1.Checked == false) {
                return list;
            }
            foreach (string key in regexMap.Keys)
            {
                Regex rg = regexMap[key];
                MatchCollection matchCollection = rg.Matches(content);
                if (matchCollection.Count > 0) {
                    foreach (Match match in matchCollection)
                    {
                        string find = match.Groups[1].Value;
                        string replace = dealDateTime(find, key);
                        //Console.WriteLine(find + "|" + replace);
                        list.Add(find+"|"+replace); 
                    }
                }
            }
            return list;
        }

        private string dealDateTime(string s, string format)
        {
            try
            {

                if (format == "yyyyMMdd")
            {
                DateTime dt;
                dt = DateTime.ParseExact(s, format, System.Globalization.CultureInfo.CurrentCulture);
                int mounth = (int)numericUpDown1.Value;
                dt = dt.AddMonths(mounth);
                string rs = dt.ToString(format);
                return rs;
            }
            else {
                DateTime dt;
                DateTimeFormatInfo dtFormat = new DateTimeFormatInfo();
                dtFormat.ShortDatePattern = format;
                dt = Convert.ToDateTime(s, dtFormat);
                int mounth = (int)numericUpDown1.Value;
                dt = dt.AddMonths(mounth);
                string rs = dt.ToString(format);
                return rs;
            }

                
            }
            catch(Exception ex) {
                Console.WriteLine(ex.Message);
                Console.WriteLine(s + " " + format);
                return s;
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (listBox1.Items.Count > 0) {     
                
                doJob();
            }
        }

        private void doJob() {                     
            setLableText();
            setStartState();
            clearProcess();
            List<string> list = new List<string>();
            foreach (string file in listBox1.Items) {
                list.Add(file);
            }
            List<Task> taskList = new List<Task>();
          
            foreach (string file in list)
            {
                taskList.Add(Task.Factory.StartNew(async () =>
                {
                    
                    try
                    {
                        if (file.EndsWith(".doc") || file.EndsWith(".docx"))
                        {
                            wordReplace(file);
                        }
                        else if (file.EndsWith(".xls") || file.EndsWith(".xlsx"))
                        {
                            excelReplace(file);
                        }
                        proccessIncreace(file);
                    }
                    finally {  }
                    
                }));
            }

            int count = (int)numericUpDown2.Value;
            TaskFactory taskFactory = new TaskFactory(new LimitedConcurrencyLevelTaskScheduler(count));
            taskList.Add(taskFactory.ContinueWhenAll(taskList.ToArray(), tArray =>
            {
                setFinishState();
                clearProcess();

            }));
        }

        private void clearProcess() {
            foreach (Process p in Process.GetProcesses())
            {
                if (p.ProcessName == "wps"||p.ProcessName == "et")
                {
                    try
                    {
                        p.Kill();
                        p.WaitForExit();
                    }
                    catch
                    {

                    }
                }
            }
        }

        private void setStartState() {
            progressBar1.Value = 0;
            progressBar1.Maximum = listBox1.Items.Count;
            button1.Enabled = false;
            button2.Enabled = false;
        }

        private void setFinishState() {           
            MethodInvoker m = new MethodInvoker(() =>
            {
                button1.Enabled = true;
                button2.Enabled = true;
                MessageBox.Show("替换完成");
            });
            this.Invoke(m);
        }

        private void proccessIncreace(string path) {          
            MethodInvoker m = new MethodInvoker(() =>
            {
                listBox1.Items.Remove(path);
                progressBar1.Increment(1);               
            });
            this.Invoke(m);
            setLableText();
        }

        private void button1_Click_1(object sender, EventArgs e)
        {
          DialogResult dr =   folderBrowserDialog1.ShowDialog();
          if (dr == DialogResult.OK) {
              string path =  folderBrowserDialog1.SelectedPath;
              textBox1.Text = path;
              List<string> files = listFileByPath(path);
              listBox1.Items.AddRange(files.ToArray());
              setLableText();
            }
        }

        private void ReplaceFileName(string path) { 
           
        }

        

        private List<string> listFileByPath(string path) {
            List<string> list = new List<string>();
            string[] files = Directory.GetFiles(path);
            foreach (string file in files)
            {
                FileInfo fileInfo = new FileInfo(file);
                if (fileInfo.Attributes.ToString().Contains("Hidden")||fileInfo.IsReadOnly)
                {
                    continue;
                }
                if (extends.Contains(fileInfo.Extension))
                {
                    if (checkBox3.Checked)
                    {
                        string fileName = fileInfo.Name;

                        List<string> replaceList = getRepalce(fileName);
                        replaceList.AddRange(others);

                        foreach (string replace in replaceList) {
                            if (string.IsNullOrEmpty(replace) || replace.Contains("|") == false) continue;
                            int index = replace.LastIndexOf("|");
                            string find = replace.Substring(0, index);
                            string rp = replace.Substring(index + 1);
                            fileName = fileName.Replace(find, rp);
                        }
                        MatchCollection matchCollection1 = regex6.Matches(fileName);
                        foreach (Match match1 in matchCollection1) {
                            string find = match1.Groups[1].Value;
                            string replace = dealDateTime(find, "yyyyMMdd");
                            fileName = fileName.Replace(find, replace);
                        }

                        string destFileName = file.Replace(fileInfo.Name, "") + fileName;
                        if (destFileName != file) { 
                            fileInfo.CopyTo(destFileName);
                            fileInfo.Delete();
                        }
                        list.Add(destFileName);
                    }
                    else {
                        list.Add(file);
                    }
                   
                }
            }
            string[] paths = Directory.GetDirectories(path);
            foreach (string p in paths)
            {
                list.AddRange(listFileByPath(p));
            }

            return list;
        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listBox1.SelectedItem != null)
            {
                string path = listBox1.SelectedItem.ToString(); 
                int index = path.LastIndexOf(@"\");
                string name = path.Substring(index + 1);
                textBox2.Text = name;
            }
        }

        private void listBox1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (listBox1.SelectedItem != null)
            {
                string path = listBox1.SelectedItem.ToString();
                int index = path.LastIndexOf(@"\");
                string p = path.Substring(0,index );
                System.Diagnostics.Process.Start("explorer.exe", p);
            }
        }

        private void textBox3_Leave(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(textBox3.Text)) {
                others.Clear();
                others.AddRange(textBox3.Lines);
                File.WriteAllText("other.txt",textBox3.Text);
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            MonitorWindows();
        }
    }

 
}
